home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1997 February / EnigmA AMIGA RUN 15 (1997)(G.R. Edizioni)(IT)[!][issue 1997-02][PLANET CD V].iso / enigma / earcd / emula / msh-156.lha / util / fmtmain.c < prev    next >
C/C++ Source or Header  |  1996-12-22  |  22KB  |  1,015 lines

  1. /*-
  2.  * $Id: fmtmain.c,v 1.56 1996/12/22 00:22:33 Rhialto Rel $
  3.  * $Log: fmtmain.c,v $
  4.  * Revision 1.56  1996/12/22  00:22:33  Rhialto
  5.  * Cosmetics.
  6.  *
  7.  * Revision 1.55  1993/12/30  23:28:00    Rhialto
  8.  * Freeze for MAXON5.
  9.  * New GadToolBox (2.0c), and use font-sensitive option.
  10.  *
  11.  * Revision 1.54  1993/06/24  05:35:45    Rhialto
  12.  * changing SPT,NSIDES,NCYLS didn't update SPF.
  13.  * DICE 2.07.54R.
  14.  *
  15.  * Revision 1.53  92/10/25  02:48:07  Rhialto
  16.  * Initial revision.
  17.  *
  18.  *  FMT MAIN.C
  19.  *
  20.  *  The main file of the MSH formatting utility.
  21.  *
  22.  *  This code is (C) Copyright 1992 by Olaf Seibert. All rights reserved.
  23.  *  May not be used or copied without a licence.
  24. -*/
  25.  
  26. #define INTUI_V36_NAMES_ONLY
  27.  
  28. #include "han.h"
  29.  
  30. #ifndef LIBRARIES_GADTOOLS_H
  31. #include <libraries/gadtools.h>
  32. #endif
  33. #ifndef INTUITION_GADGETCLASS_H
  34. #include <intuition/gadgetclass.h>
  35. #endif
  36. #ifndef DOS_DOS_H
  37. #include <dos/dos.h>
  38. #endif
  39. #ifndef DOS_DOSEXTENS_H
  40. #include <dos/dosextens.h>
  41. #endif
  42. #ifndef DOS_FILEHANDLER_H
  43. #include <dos/filehandler.h>
  44. #endif
  45. #ifndef EXEC_MEMORY_H
  46. #include <exec/memory.h>
  47. #endif
  48.  
  49. #include <stdio.h>
  50. #include <stdlib.h>
  51. #include <string.h>
  52. #include <stdarg.h>
  53.  
  54. #include <clib/exec_protos.h>
  55. #include <clib/intuition_protos.h>
  56. #include <clib/gadtools_protos.h>
  57. #include <clib/alib_protos.h>
  58. #include <clib/dos_protos.h>
  59.  
  60. #include "fmtwindow.h"
  61.  
  62. struct Library *GadToolsBase;
  63. struct IntuituinBase *IntuitionBase;
  64.  
  65. struct MinList    MSHList;
  66. struct MSHNode {
  67.     struct Node     m_Node;
  68.     struct DosList *m_DosList;
  69.     char        m_Name[2];    /* 1 for ':', 1 for '\0' */
  70. };
  71.  
  72. struct DosList *HandlerDList;
  73. char           *HandlerName;
  74. char           *DevName;
  75. long        DevUnit;
  76. unsigned long    DevFlags;
  77.  
  78. const char    OkString[] = "Ok";
  79. const char    AbortString[] = "Abort";
  80. const char    PanicString[] = "Panic!";
  81. const char    RCSId[] = "\0$\VER: MSH-Format $Revision: 1.56 $ $Date: 1996/12/22 00:22:33 $, by Olaf Seibert";
  82.  
  83. void        Show(void);
  84. void        Hide(void);
  85. void        HideParm(void);
  86. void        SetGadgetAttrM(int id, ULONG tag, ULONG value);
  87. void        SetGadgetAttrP(int id, ULONG tag, ULONG value);
  88. void        SetStringDefaults(void);
  89. void        UpdateStrings(void);
  90.  
  91. #define DONE_DONE   1
  92. #define DONE_RESET  2
  93. #define DONE_HIDEP  4
  94.  
  95. const ulong    BootBlock[] = {
  96.     0xEB349049, 0x424D2020, 0x332E3200, 0x02020100,    /* ...IBM  3.2..... */
  97.     0x027000A0, 0x05F90300, 0x09000200, 0x00000000,
  98.     0x00000000, 0x00000000, 0x00000000, 0x0000000F,
  99.     0x00000000, 0x0100FA33, 0xC08ED0BC, 0x007C1607,
  100.     0xBB780036, 0xC5371E56, 0x1653BF2B, 0x7CB90B00,
  101.     0xFCAC2680, 0x3D007403, 0x268A05AA, 0x8AC4E2F1,
  102.     0x061F8947, 0x02C7072B, 0x7CFBCD13, 0x7267A010,
  103.     0x7C98F726, 0x167C0306, 0x1C7C0306, 0x0E7CA33F,
  104.     0x7CA3377C, 0xB82000F7, 0x26117C8B, 0x1E0B7C03,
  105.     0xC348F7F3, 0x0106377C, 0xBB0005A1, 0x3F7CE896,
  106.     0x00B80102, 0xE8AA0072, 0x198BFBB9, 0x0B00BECD,
  107.     0x7DF3A675, 0x0D8D7F20, 0xBED87DB9, 0x0B00F3A6,
  108.     0x7418BE6E, 0x7DE86100, 0x32E4CD16, 0x5E1F8F04,
  109.     0x8F4402CD, 0x19BEB77D, 0xEBEBA11C, 0x0533D2F7,
  110.     0x360B7CFE, 0xC0A23C7C, 0xA1377CA3, 0x3D7CBB00,
  111.     0x07A1377C, 0xE84000A1, 0x187C2A06, 0x3B7C4050,
  112.     0xE84E0058, 0x72CF2806, 0x3C7C760C, 0x0106377C,
  113.     0xF7260B7C, 0x03D8EBD9, 0x8A2E157C, 0x8A16FD7D,
  114.     0x8B1E3D7C, 0xEA000070, 0x00AC0AC0, 0x7422B40E,
  115.     0xBB0700CD, 0x10EBF233, 0xD2F73618, 0x7CFEC288,
  116.     0x163B7C33, 0xD2F7361A, 0x7C88162A, 0x7CA3397C,
  117.     0xC3B4028B, 0x16397CB1, 0x06D2E60A, 0x363B7C8B,
  118.     0xCA86E98A, 0x16FD7D8A, 0x362A7CCD, 0x13C30D0A,
  119.     0x4E6F6E2D, 0x53797374, 0x656D2064, 0x69736B20,    /* Non-System disk  */
  120.     0x6F722064, 0x69736B20, 0x6572726F, 0x720D0A52,    /* or disk error..R */
  121.     0x65706C61, 0x63652061, 0x6E642073, 0x7472696B,    /* eplace and strik */
  122.     0x6520616E, 0x79206B65, 0x79207768, 0x656E2072,    /* e any key when r */
  123.     0x65616479, 0x0D0A000D, 0x0A446973, 0x6B20426F,    /* eady.....Disk Bo */
  124.     0x6F742066, 0x61696C75, 0x72650D0A, 0x0049424D,    /* ot failure...IBM */
  125.     0x42494F20, 0x20434F4D, 0x49424D44, 0x4F532020,    /* BIO    COMIBMDOS   */
  126.     0x434F4D00, 0x00000000, 0x00000000, 0x00000000,    /* COM............. */
  127.     0x00000000, 0x00000000, 0x00000000, 0x000055AA,
  128. };
  129.  
  130. byte           *DiskTrack;
  131. long        TrackSize;
  132. int        Track;
  133. int        EndTrack;
  134. struct IOExtTD *TDReq;
  135. int        Break;
  136.  
  137. int        Parameters[13];
  138. int        FormatWhat;
  139. #define BOOT_ONLY   0
  140. #define BOOT_ROOT   1
  141. #define WHOLE_DISK  2
  142.  
  143. #define BPS    Parameters[GDX_BPS]
  144. #define SPT    Parameters[GDX_SPT]
  145. #define NSIDES    Parameters[GDX_NSIDES]
  146. #define FIRSTCYL Parameters[GDX_FIRSTCYL]
  147. #define NCYLS    Parameters[GDX_NCYLS]
  148. #define SPC    Parameters[GDX_SPC]
  149. #define RESERVED Parameters[GDX_RESERVED]
  150. #define NFATS    Parameters[GDX_NFATS]
  151. #define NDIRS    Parameters[GDX_NDIRS]
  152. #define NSECTS    Parameters[GDX_NSECTS]
  153. #define MEDIA    Parameters[GDX_MEDIA]
  154. #define SPF    Parameters[GDX_SPF]
  155. #define NHID    Parameters[GDX_NHID]
  156.  
  157. int
  158. todigit(char   c)
  159. {
  160.     if ((c -= '0') < 0 || c > ('F' - '0'))
  161.     return 42;
  162.  
  163.     if (c >= ('A' - '0')) {
  164.     c -= 'A' - '9' - 1;
  165.     }
  166.     return c;
  167. }
  168.  
  169. long
  170. ntoi(char  *str)
  171. {
  172.     long        total = 0;
  173.     long        value;
  174.     int         digit;
  175.     int         base;
  176.  
  177.     /* First determine the base */
  178. number:
  179.     if (*str == '0') {
  180.     if (*++str == 'x') {    /* 0x means hexadecimal */
  181.         base = 16;
  182.         str++;
  183.     } else {
  184.         base = 8;        /* Otherwise, 0 means octal */
  185.     }
  186.     } else {
  187.     base = 10;        /* and any other digit means decimal */
  188.     }
  189.  
  190.     value = 0;
  191.     while ((digit = todigit(*str)) < base) {
  192.     value *= base;
  193.     value += digit;
  194.     str++;
  195.     }
  196.  
  197. suffix:
  198.     switch (*str++) {
  199.     case 'm':                   /* scale with megabytes */
  200.     value *= 1024L * 1024;
  201.     goto suffix;
  202.     case 'k':                   /* scale with kilobytes */
  203.     value *= 1024;
  204.     goto suffix;
  205.     case 's':                   /* scale with sectors */
  206.     value *= TD_SECTOR;    /* or maybe even kilosectors! */
  207.     goto suffix;
  208.     case 'b':                   /* scale with bytes */
  209.     goto suffix;
  210.     }
  211.     str--;
  212.  
  213.     total += value;
  214.  
  215.     if (*str >= '0' && *str <= '9')
  216.     goto number;        /* Allow 10k512, recursion eliminated */
  217.  
  218.     return total;
  219. }
  220.  
  221. char *
  222. iton(char *string, int size, int value)
  223. {
  224.     if (value >= 1024 * 1024L) {
  225.     int        m;
  226.     int        rest;
  227.     char           *last;
  228.  
  229.     m = value / (1024 * 1024L);
  230.     rest = value - (m * 1024L * 1024);
  231.     last = iton(string, size, m);
  232.     *last++ = 'm';
  233.     size -= (last - string);
  234.     value = rest;
  235.     string = last;
  236.     }
  237.  
  238.     if (value >= 64 * 1024) {
  239.     int        k;
  240.     int        rest;
  241.     char           *last;
  242.  
  243.     k = value / 1024;
  244.     rest = value - (k * 1024);
  245.     last = iton(string, size, k);
  246.     *last++ = 'k';
  247.     size -= (last - string);
  248.     value = rest;
  249.     string = last;
  250.     }
  251.     sprintf(string, "%d", value);
  252.     while (*string)
  253.     string++;
  254.  
  255.     return string;
  256. }
  257.  
  258.  
  259. void
  260. PutWord(byte *address, word value)
  261. {
  262.     address[0] = value;
  263.     address[1] = value >> 8;
  264. }
  265.  
  266.  
  267. void
  268. Die(void)
  269. {
  270.     Hide();
  271.  
  272.     if (IntuitionBase) {
  273.     CloseLibrary(IntuitionBase);
  274.     IntuitionBase = NULL;
  275.     }
  276.     if (GadToolsBase) {
  277.     CloseLibrary(GadToolsBase);
  278.     GadToolsBase = NULL;
  279.     }
  280.     exit(0);
  281. }
  282.  
  283. void
  284. OpenAll(int argc, char **argv)
  285. {
  286.     extern struct Library *DOSBase;
  287.  
  288.     NewList((struct List *) &MSHList);
  289.  
  290.     if (DOSBase->lib_Version < 37) {
  291.     puts("Sorry, requires at least V37...");
  292.     Die();
  293.     }
  294.     GadToolsBase = OpenLibrary("gadtools.library", 37L);
  295.     if (!GadToolsBase)
  296.     Die();
  297.  
  298.     IntuitionBase = OpenLibrary("intuition.library", 37L);
  299.     if (!IntuitionBase)
  300.     Die();
  301.  
  302.     Show();
  303. }
  304.  
  305. int
  306. isFileSystem(struct MsgPort *handler)
  307. {
  308.     if (handler == NULL)
  309.     return FALSE;
  310.  
  311.     if (DoPkt(handler, ACTION_IS_FILESYSTEM, 0, 0, 0, 0, 0)) {
  312.     return TRUE;
  313.     }
  314.     return FALSE;
  315. }
  316.  
  317. void
  318. FindAllDevices(void)
  319. {
  320.     struct DosList *dlist;
  321.  
  322.     dlist = LockDosList(LDF_DEVICES | LDF_READ);
  323.  
  324.     while (dlist = NextDosEntry(dlist, LDF_DEVICES)) {
  325.     if (dlist->dol_misc.dol_handler.dol_Startup > 100 &&
  326.         isFileSystem(dlist->dol_Task)) {
  327.         char       *name;
  328.         struct MSHNode *node;
  329.  
  330.         name = (char *) BADDR(dlist->dol_Name);
  331.         node = AllocVec(sizeof (*node) + name[0], MEMF_CLEAR);
  332.         if (node) {
  333.         strncpy(node->m_Name, &name[1], name[0]);
  334.         strcpy(node->m_Name + name[0], ":");
  335.  
  336.         node->m_Node.ln_Name = node->m_Name;
  337.         node->m_DosList = dlist;
  338.         AddHead((struct List *) &MSHList, &node->m_Node);
  339.         }
  340.     }
  341.     }
  342.  
  343.     UnLockDosList(LDF_DEVICES | LDF_READ);
  344. }
  345.  
  346. void
  347. ForgetAllDevices(void)
  348. {
  349.     struct Node    *n,
  350.            *nn;
  351.  
  352.     n = (struct Node *)MSHList.mlh_Head;
  353.     while (nn = n->ln_Succ) {
  354.     FreeVec(n);
  355.     n = nn;
  356.     }
  357.     NewList((struct List *) &MSHList);
  358. }
  359.  
  360. void
  361. Show(void)
  362. {
  363.     if (MainWnd) {
  364.     WindowToFront(MainWnd);
  365.     return;         /* already open */
  366.     }
  367.  
  368.     if (SetupScreen())
  369.     Die();
  370.  
  371.     if (OpenMainWindow())
  372.     Die();
  373.  
  374.     FindAllDevices();
  375.     SetGadgetAttrM(GDX_HANDLERS, GTLV_Labels, (ULONG) &MSHList);
  376. }
  377.  
  378. void
  379. ShowParm(void)
  380. {
  381.     if (ParmWnd) {
  382.     WindowToFront(ParmWnd);
  383.     return;         /* already open */
  384.     }
  385.  
  386.     if (OpenParmWindow())
  387.     return;
  388.  
  389.     /* Compensate for a bug in GadToolsBox 1.3: */
  390.     ModifyIDCMP(ParmWnd,
  391.         ParmWnd->IDCMPFlags | STRINGIDCMP | BUTTONIDCMP);
  392.  
  393.     UpdateStrings();
  394. }
  395.  
  396. void
  397. Hide(void)
  398. {
  399.     HideParm();
  400.  
  401.     if (MainWnd) {
  402.     struct IntuiMessage *msg;
  403.  
  404.     while (msg = GT_GetIMsg(MainWnd->UserPort)) {
  405.         GT_ReplyIMsg(msg);
  406.     }
  407.     }
  408.  
  409.     CloseMainWindow();
  410.     CloseDownScreen();
  411.     ForgetAllDevices();
  412. }
  413.  
  414. void
  415. HideParm(void)
  416. {
  417. #if 0
  418.     if (ParmWnd) {
  419.     struct IntuiMessage *msg;
  420.  
  421.     while (msg = GT_GetIMsg(ParmWnd->UserPort)) {
  422.         GT_ReplyIMsg(msg);
  423.     }
  424.     }
  425. #endif
  426.     CloseParmWindow();
  427. }
  428.  
  429. struct MSHNode       *
  430. GetNode(struct MinList *l, int num)
  431. {
  432.     struct Node    *n,
  433.            *nn;
  434.  
  435.     n = (struct Node *)l->mlh_Head;
  436.     while (num > 0 && (nn = n->ln_Succ)) {
  437.     num--;
  438.     n = nn;
  439.     }
  440.  
  441.     return n;
  442. }
  443.  
  444. void
  445. DeselectHandler(void)
  446. {
  447.     HandlerDList = NULL;
  448. }
  449.  
  450. void
  451. SelectHandler(struct MSHNode *node)
  452. {
  453.     struct DosList *dl;
  454.     struct FileSysStartupMsg *fssm;
  455.  
  456.     DeselectHandler();
  457.  
  458.     HandlerName = node->m_Node.ln_Name;
  459.     dl = node->m_DosList;
  460.     HandlerDList = dl;
  461.     fssm = (struct FileSysStartupMsg *)BADDR(dl->dol_misc.dol_handler.dol_Startup);
  462.     DevName = ((char *)BADDR(fssm->fssm_Device)) + 1;
  463.     DevFlags = fssm->fssm_Flags;
  464.     DevUnit = fssm->fssm_Unit;
  465.     SetStringDefaults();
  466. }
  467.  
  468. void
  469. SetGadgetAttrM(int id, ULONG tag, ULONG value)
  470. {
  471.     GT_SetGadgetAttrs(MainGadgets[id], MainWnd, NULL,
  472.               tag, value,
  473.               TAG_END);
  474. }
  475.  
  476. void
  477. SetGadgetAttrP(int id, ULONG tag, ULONG value)
  478. {
  479.     if (ParmWnd) {
  480.     GT_SetGadgetAttrs(ParmGadgets[id], ParmWnd, NULL,
  481.               tag, value,
  482.               TAG_END);
  483.     }
  484. }
  485.  
  486. void
  487. UpdateString(int id)
  488. {
  489.     char        newstring[80];
  490.  
  491.     iton(newstring, sizeof newstring, Parameters[id]);
  492.     SetGadgetAttrP(id, GTST_String, (ULONG)newstring);
  493. }
  494.  
  495. void
  496. UpdateStrings(void)
  497. {
  498.     int         i;
  499.  
  500.     if (!ParmWnd) {
  501.     return;
  502.     }
  503.  
  504.     for (i = 0; i < GDX_OK; i++) {    /* 0 == GDX_BPS */
  505.     UpdateString(i);
  506.     }
  507. }
  508.  
  509. void
  510. MotorOff(void)
  511. {
  512.     TDReq->iotd_Req.io_Command = TD_MOTOR;
  513.     TDReq->iotd_Req.io_Length = 0;
  514.     DoIO((struct IORequest *)TDReq);
  515. }
  516.  
  517. int
  518. IgnoreAbortRetry(char *fmt, ...)
  519. {
  520.     static struct EasyStruct er0 = {
  521.     sizeof er0, 0, PanicString,
  522.     NULL,
  523.     "Abort|Retry|Ignore"
  524.     };
  525.     struct EasyStruct er;
  526.     va_list        va;
  527.  
  528.     MotorOff();
  529.     er = er0;
  530.     er.es_TextFormat = fmt;
  531.     va_start(va, fmt);
  532.       return EasyRequestArgs(MainWnd, &er, NULL, va);
  533.     va_end(va)        /* produces error if it doesn't expand to empty */
  534. }
  535.  
  536. int
  537. Confirm(char *fmt, char *buttons, ...)
  538. {
  539.     static struct EasyStruct er0 = {
  540.     sizeof er0, 0, "MSH Format",
  541.     NULL,
  542.     NULL
  543.     };
  544.     struct EasyStruct er;
  545.     va_list        va;
  546.  
  547.     er = er0;
  548.     er.es_TextFormat = fmt;
  549.     er.es_GadgetFormat = buttons;
  550.     va_start(va, buttons);
  551.       return EasyRequestArgs(MainWnd, &er, NULL, va);
  552.     va_end(va)        /* produces error if it doesn't expand to empty */
  553. }
  554.  
  555. /*
  556.  * Look through incoming messages to see if the user is playing
  557.  * with the gadgets. If so, ask if she wants to stop formatting.
  558.  */
  559.  
  560. int
  561. CheckCancel(void)
  562. {
  563.     if (MainWnd) {
  564.     struct IntuiMessage *msg, *next;
  565.  
  566.     msg = (struct IntuiMessage *)MainWnd->UserPort->mp_MsgList.lh_Head;
  567.     while (next = (struct IntuiMessage *)msg->ExecMessage.mn_Node.ln_Succ) {
  568.         if (msg->Class & (IDCMP_GADGETUP | IDCMP_GADGETDOWN |
  569.                   IDCMP_CLOSEWINDOW)) {
  570.         Remove(&msg->ExecMessage.mn_Node);
  571.         ReplyMsg(&msg->ExecMessage);
  572.  
  573.         MotorOff();
  574.         Break = Confirm("Stop formatting?", "Stop|Continue");
  575.         return Break;
  576.         }
  577.         msg = next;
  578.     }
  579.     }
  580.  
  581.     return 0;
  582. }
  583.  
  584. void
  585. Title(char *fmt, int t, int s)
  586. {
  587.     static char buf[80];
  588.  
  589.     sprintf(buf, fmt, t, s);
  590.     SetWindowTitles(MainWnd, buf, (char *)-1);
  591. }
  592.  
  593. byte           *
  594. MaybeWrite(byte *block)
  595. {
  596.     while (Break == 0 &&
  597.        block >= (DiskTrack + TrackSize)) {
  598.     char           *msg;
  599.     int        t,
  600.             s;
  601.  
  602.     t = Track / NSIDES;
  603.     s = Track % NSIDES;
  604.     top:
  605.     CheckCancel();
  606.     if (Break)
  607.         break;
  608.     Title("Writing cylinder %3d side %d...", t, s);
  609.     TDReq->iotd_Req.io_Command = TD_FORMAT;
  610.     TDReq->iotd_Req.io_Data = (APTR) DiskTrack;
  611.     TDReq->iotd_Req.io_Length = TrackSize;
  612.     TDReq->iotd_Req.io_Offset = TrackSize * Track;
  613.     DoIO((struct IORequest *)TDReq);
  614.     if (TDReq->iotd_Req.io_Error) {
  615.         msg = "Write";
  616.         goto error;
  617.     }
  618.     TDReq->iotd_Req.io_Command = CMD_UPDATE;
  619.     DoIO((struct IORequest *)TDReq);
  620.     if (TDReq->iotd_Req.io_Error) {
  621.         msg = "Update";
  622.         goto error;
  623.     }
  624.     TDReq->iotd_Req.io_Command = CMD_CLEAR;
  625.     DoIO((struct IORequest *)TDReq);
  626.  
  627.     Title("Reading cylinder %3d side %d...", t, s);
  628.     TDReq->iotd_Req.io_Command = CMD_READ;
  629.     TDReq->iotd_Req.io_Data = (APTR) DiskTrack;
  630.     TDReq->iotd_Req.io_Length = TrackSize;
  631.     TDReq->iotd_Req.io_Offset = TrackSize * Track;
  632.     DoIO((struct IORequest *)TDReq);
  633.     if (TDReq->iotd_Req.io_Error) {
  634.         msg = "Read";
  635.     error:
  636.         Break = IgnoreAbortRetry("%s error %ld on\ncylinder %ld side %ld.\n",
  637.            msg, TDReq->iotd_Req.io_Error, t, s);
  638.         if (Break == 2) {
  639.         Break = 0;
  640.         goto top;
  641.         }
  642.     }
  643.     setmem(DiskTrack, (int) TrackSize, 0);
  644.     Track++;
  645.     if ((block -= TrackSize) < DiskTrack)
  646.         block = DiskTrack;
  647.     }
  648.     return block;
  649. }
  650.  
  651. int
  652. DoFormat(void)
  653. {
  654.     struct MsgPort *port;
  655.     byte       *diskBlock;
  656.     char       *title;
  657.     int         i;
  658.  
  659.     Break = 0;
  660.     title = MainWnd->Title;
  661.  
  662.     if (!(port = CreatePort(NULL, 0L))) {
  663.     DisplayBeep(NULL);
  664.     goto abort1;
  665.     }
  666.     if (!(TDReq = (struct IOExtTD *)CreateExtIO(port, (long) sizeof(*TDReq)))) {
  667.     DisplayBeep(NULL);
  668.     goto abort2;
  669.     }
  670.     if (OpenDevice(DevName, DevUnit, (struct IORequest *)TDReq, 0L)) {
  671.     Confirm("Cannot OpenDevice %s", AbortString, DevName);
  672.     goto abort3;
  673.     }
  674.  
  675.     TrackSize = BPS * SPT;
  676.     Track = FIRSTCYL * NSIDES;
  677.     EndTrack = Track + NSIDES * NCYLS;
  678.  
  679.     if ((DiskTrack = AllocMem(TrackSize,
  680.             MEMF_PUBLIC | MEMF_CHIP | MEMF_CLEAR)) == NULL) {
  681.     Confirm("No memory for track buffer\n(%ld bytes of chipmem)", NULL, TrackSize);
  682.     goto abort4;
  683.     }
  684.     CopyMem((char *)BootBlock, DiskTrack, (long) sizeof (BootBlock));
  685.  
  686.     PutWord(DiskTrack + 0x0b,    BPS);
  687.       *(DiskTrack + 0x0d) = SPC;
  688.     PutWord(DiskTrack + 0x0e,    RESERVED);
  689.       *(DiskTrack + 0x10) = NFATS;
  690.     PutWord(DiskTrack + 0x11,    NDIRS);
  691.     PutWord(DiskTrack + 0x13,    NSECTS);
  692.       *(DiskTrack + 0x15) = MEDIA;
  693.     PutWord(DiskTrack + 0x16,    SPF);
  694.     PutWord(DiskTrack + 0x18,    SPT);
  695.     PutWord(DiskTrack + 0x1a,    NSIDES);
  696.     PutWord(DiskTrack + 0x1c,    NHID);
  697.  
  698.     Break = Confirm("Insert disk to be formatted in\n%s unit %ld",
  699.         "Cancel|Format",
  700.         DevName, DevUnit);
  701.     if (Break)
  702.     return 1;
  703.  
  704.     if (!Inhibit(HandlerName, DOSTRUE)) {
  705.     Confirm("Cannot inhibit %s!", AbortString, HandlerName);
  706.     goto done;
  707.     }
  708.  
  709.     if (FormatWhat == BOOT_ONLY) {
  710.     top:
  711.     Title("Writing bootblock only.", 0, 0);
  712.     TDReq->iotd_Req.io_Command = CMD_WRITE;
  713.     TDReq->iotd_Req.io_Data = (APTR) DiskTrack;
  714.     TDReq->iotd_Req.io_Length = sizeof (BootBlock);
  715.     TDReq->iotd_Req.io_Offset = 0;
  716.     DoIO((struct IORequest *)TDReq);
  717.  
  718.     if (TDReq->iotd_Req.io_Error) {
  719.         Break = IgnoreAbortRetry("Write error %ld!",
  720.             TDReq->iotd_Req.io_Error);
  721.         if (Break == 2) {
  722.         Break = 0;
  723.         goto top;
  724.         }
  725.     }
  726.     if (!Break) {
  727.         TDReq->iotd_Req.io_Command = CMD_UPDATE;
  728.         DoIO((struct IORequest *)TDReq);
  729.     }
  730.  
  731.     goto done;
  732.     }
  733.  
  734.     /* Go to first FAT */
  735.     diskBlock = MaybeWrite(DiskTrack + BPS * RESERVED);
  736.     for (i = 0; i < NFATS; i++) {
  737.     diskBlock[0] = 0xF9;
  738.     diskBlock[1] = 0xFF;
  739.     diskBlock[2] = 0xFF;
  740.     diskBlock = MaybeWrite(diskBlock + BPS * SPF);    /* Next FAT */
  741.     }
  742.  
  743.     /* Clear entire directory */
  744.     diskBlock = MaybeWrite(diskBlock + NDIRS * MS_DIRENTSIZE);
  745.     MaybeWrite(DiskTrack + TrackSize);    /* Force a write */
  746.  
  747.     if (FormatWhat == WHOLE_DISK) {
  748.     while (Track < EndTrack) {
  749.         MaybeWrite(DiskTrack + TrackSize);    /* Write an empty track */
  750.         if (Break)
  751.         break;
  752.     }
  753.     }
  754.  
  755. done:
  756.     MotorOff();
  757.     TDReq->iotd_Req.io_Command = TD_MOTOR;
  758.     TDReq->iotd_Req.io_Length = 0;
  759.     DoIO((struct IORequest *)TDReq);
  760.  
  761.     SetWindowTitles(MainWnd, title, (char *)-1);
  762.     if (!Break)
  763.     Confirm("Format finished.", OkString);
  764.     Inhibit(HandlerName, DOSFALSE);
  765.  
  766. abort5:
  767.     FreeMem(DiskTrack, TrackSize);
  768. abort4:
  769.     CloseDevice((struct IORequest *)TDReq);
  770. abort3:
  771.     DeleteExtIO((struct IORequest *)TDReq);
  772. abort2:
  773.     DeletePort(port);
  774. abort1:;
  775.  
  776.     return Break;
  777. }
  778.  
  779. void
  780. Recalculate(int id)
  781. {
  782.     long        mask;
  783.  
  784.     mask = (id < 0)? ~0 : 1L << id;
  785.  
  786.     if (mask & (1L<<GDX_SPT | 1L<<GDX_NSIDES | 1L<<GDX_NCYLS)) {
  787.     NSECTS = SPT * NSIDES * NCYLS;
  788.     UpdateString(GDX_NSECTS);
  789.     mask |= 1L<<GDX_NSECTS;
  790.     }
  791.     if (mask & (1L<<GDX_NSECTS | 1L<<GDX_SPC | 1L<<GDX_BPS)) {
  792.     /*
  793.      * Suggest a minimum value for the number of FAT sectors.
  794.      * Here we assume all sectors are to be used for clusters, which is not
  795.      * really true, but simpler, and gives a conservative value. Besides,
  796.      * the number of available sectors also depends on the FAT size, so
  797.      * the whole calculation (if done correctly) would be recursive. In
  798.      * practice, it may occasionally suggest one sector too much.
  799.      */
  800.     long        nclusters;
  801.     long        nbytes;
  802.     int        spf;
  803.  
  804.     nclusters = MS_FIRSTCLUST + (NSECTS + SPC - 1) / SPC;
  805.     if (nclusters > 0xFF7) /* 16-bit FAT entries */
  806.         nbytes = nclusters * 2;
  807.     else              /* 12-bit FAT entries */
  808.         nbytes = (nclusters * 3 + 1) / 2;
  809.     spf = (nbytes + BPS - 1) / BPS;
  810.     /* Hack for floppies */
  811.     if (spf < MS_SPF)
  812.         spf = MS_SPF;
  813.  
  814.     SPF = spf;
  815.     UpdateString(GDX_SPF);
  816.     }
  817. }
  818.  
  819. void
  820. SetStringDefaults(void)
  821. {
  822.     BPS     = MS_BPS;
  823.     SPT     = MS_SPT;
  824.     NSIDES    = MS_NSIDES;
  825.     FIRSTCYL    = 0;
  826.     NCYLS    = 80;
  827.     RESERVED    = MS_RES;
  828.     NHID    = 0;
  829.     SPC     = MS_SPC;
  830.     NFATS    = MS_NFATS;
  831.     MEDIA    = 0xF9;
  832.     NDIRS    = MS_NDIRS;
  833.  
  834.     if (HandlerDList) {
  835.     struct DosList *dl;
  836.     struct FileSysStartupMsg *fssm;
  837.     long           *environ;
  838.  
  839.     dl = HandlerDList;
  840.     fssm = (struct FileSysStartupMsg *)BADDR(dl->dol_misc.dol_handler.dol_Startup);
  841.  
  842.     if ((environ = (long *)BADDR(fssm->fssm_Environ)) &&
  843.         environ[DE_TABLESIZE] >= DE_UPPERCYL) {
  844.         NSIDES   = environ[DE_NUMHEADS];
  845.         SPT      = environ[DE_BLKSPERTRACK];
  846.         BPS      = environ[DE_SIZEBLOCK] * 4;
  847.         FIRSTCYL = environ[DE_LOWCYL];
  848.         NCYLS    = environ[DE_UPPERCYL] - FIRSTCYL + 1;
  849.     }
  850.     }
  851.     Recalculate(-1);
  852.     UpdateStrings();
  853. }
  854.  
  855. int
  856. DoGadget(struct IntuiMessage *imsg)
  857. {
  858.     struct Gadget  *gd;
  859.     int         id;
  860.  
  861.     gd = (struct Gadget *) imsg->IAddress;
  862.     id = gd->GadgetID;
  863.  
  864.     switch (id) {
  865.     case GD_HANDLERS:
  866.     {
  867.         struct MSHNode *n;
  868.  
  869.         n = GetNode(&MSHList, imsg->Code);
  870.         SelectHandler(n);
  871.         SetGadgetAttrM(GDX_DOIT, GA_Disabled, FALSE);
  872.         SetGadgetAttrM(GDX_OPTIONS, GA_Disabled, FALSE);
  873.     }
  874.     break;
  875.     case GD_FMT_WHAT:
  876.     FormatWhat = imsg->Code;
  877.     break;
  878.     case GD_OPTIONS:
  879.     ShowParm();
  880.     return 2;
  881.     case GD_DOIT:
  882.     DoFormat();
  883.     break;
  884.     case GD_CANCEL:
  885.     return DONE_DONE;
  886.  
  887.  
  888.     case GD_BPS:
  889.     case GD_SPT:
  890.     case GD_NSIDES:
  891.     case GD_FIRSTCYL:
  892.     case GD_NCYLS:
  893.     case GD_SPC:
  894.     case GD_RESERVED:
  895.     case GD_NFATS:
  896.     case GD_NDIRS:
  897.     case GD_NSECTS:
  898.     case GD_MEDIA:
  899.     case GD_SPF:
  900.     case GD_NHID:
  901.     id -= GD_BPS - GDX_BPS;     /* convert to array index */
  902.     Parameters[id] = ntoi(((struct StringInfo *)gd->SpecialInfo)->Buffer);
  903.     Recalculate(id);
  904.     break;
  905.     case GD_OK:
  906.     return DONE_HIDEP;
  907.     }
  908.  
  909.     return 0;
  910. }
  911.  
  912. struct IntuiMessage *
  913. Safe_GT_GetIMsg(struct Window *w)
  914. {
  915.     if (w)
  916.     return GT_GetIMsg(w->UserPort);
  917.     return NULL;
  918. }
  919.  
  920. void
  921. MainLoop(void)
  922. {
  923.     long        waitmask;
  924.     long        mainmask;
  925.     long        parmmask;
  926.     long        mask;
  927.     int         done;
  928.  
  929. top:
  930.     done = 0;
  931.  
  932.     if (MainWnd)
  933.     mainmask = 1L << MainWnd->UserPort->mp_SigBit;
  934.     else
  935.     mainmask = 0;
  936.  
  937.     if (ParmWnd)
  938.     parmmask = 1L << ParmWnd->UserPort->mp_SigBit;
  939.     else
  940.     parmmask = 0;
  941.  
  942.     waitmask = mainmask | parmmask | SIGBREAKF_CTRL_C;
  943.  
  944.     while (!done) {
  945.     mask = Wait(waitmask);
  946.     if (mask & SIGBREAKF_CTRL_C) {
  947.         done = DONE_DONE;
  948.         break;
  949.     }
  950.     if (mask & (mainmask | parmmask)) {
  951.         struct IntuiMessage *imsg;
  952.  
  953.         while ((imsg = Safe_GT_GetIMsg(MainWnd)) ||
  954.            (imsg = Safe_GT_GetIMsg(ParmWnd))) {
  955.         switch (imsg->Class) {
  956.         case IDCMP_CLOSEWINDOW:
  957.             if (imsg->IDCMPWindow == MainWnd) {
  958.             done = DONE_DONE;
  959.             } else {
  960.             done = DONE_HIDEP;
  961.             }
  962.             break;
  963.         case IDCMP_GADGETDOWN:
  964.         case IDCMP_GADGETUP:
  965.             done = DoGadget(imsg);
  966.             break;
  967.         case IDCMP_REFRESHWINDOW:
  968.             GT_BeginRefresh(imsg->IDCMPWindow);
  969.             GT_EndRefresh(imsg->IDCMPWindow, TRUE);
  970.             break;
  971.         }
  972.         GT_ReplyIMsg(imsg);
  973.         if (done & DONE_HIDEP) {
  974.             HideParm();
  975.             goto top;
  976.         }
  977.         }
  978.     }
  979.     if (done & DONE_RESET) {
  980.         goto top;
  981.     }
  982.     }
  983. }
  984.  
  985. void chkabort(void) {}        /* DICE specific. */
  986.  
  987. int
  988. main(int argc, char **argv)
  989. {
  990.     OpenAll(argc, argv);
  991.  
  992.     MainLoop();
  993.     Die();
  994.  
  995.     return 0;
  996. }
  997.  
  998. #ifndef WORKBENCH_STARTUP_H
  999. #include <workbench/startup.h>
  1000. #endif
  1001.  
  1002. int
  1003. wbmain(struct WBStartup *wbs)
  1004. {
  1005.     int         rc;
  1006.     long        lock;
  1007.  
  1008.     if (wbs->sm_ArgList)
  1009.     lock = CurrentDir(wbs->sm_ArgList->wa_Lock);
  1010.     rc = main(0, (char **)wbs);
  1011.     if (wbs->sm_ArgList)
  1012.     CurrentDir(lock);
  1013.     return rc;
  1014. }
  1015.